package MultiNetworkingBase;

import java.io.IOException;
import java.util.ArrayList;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.EndPoint;
import com.esotericsoftware.kryonet.Listener;

//TODO: Have the join game page call create setUpClientAndServer with a parameter that holds the host

public class Network {
    static public final int port = 54555;
    
    private WarTugServer server;
	private Thread serverThread;
	private Client client; //Receives the network connections
	private boolean runningServer; //Does this Network instance have a serverThread
	private UnitManager uManager;
	
	public Network(UnitManager uMan) {
		uManager = uMan;
	}
    
    public void setUpClientAndServer(boolean createServer, String host) {
		if (createServer){
			makeServer();
		}
		makeClient(host);
	}
    
    private void makeServer(){
		runningServer = true;
    	try{
    		server = new WarTugServer();
    		serverThread = new Thread(server);
    		serverThread.start();
    	} catch (IOException e) {
    		System.err.println("Error Starting Server...");
    		System.exit(-1);
    	}
	}
	
	private void makeClient(String host) {
		client = new Client();
        client.start();

        // For consistency, the classes to be sent over the network are
        // registered by the same method for both the client and server.
        Network.register(client);

        client.addListener(new Listener() { //Add listener to the client
                public void connected (Connection connection) {
                        RegisterName registerName = new RegisterName();
                        registerName.name = WarTug.name; //TODO: THis needs to know the name of the player
                        client.sendTCP(registerName);
                }

                public void received (Connection connection, Object object) {
                        if (object instanceof SimpleUnit) {
                        	uManager.addUnit((SimpleUnit) object);
                        	return;
                        }
                }

                public void disconnected (Connection connection) {
                	//Here put code to stop client if it loses connection to server, maybe just set a variable
                }
        });
        
        try {
			client.connect(5000, host, Network.port); //Connect to the server
		} catch (IOException e) { e.printStackTrace(); }
	}
	
	public void endNetworkConnection() {
		//cleanup and end
		client.close();
		client.stop();
		if (runningServer){
			server.end = true;
			try {
				Thread.sleep(200);  //Wait to ensure that the server has actually exited
			} catch (InterruptedException e) { e.printStackTrace();	}

			server.server.close();
			server.server.stop();
			try {
				System.out.println("Waiting for server to quit...");
				serverThread.join();
				System.out.println("Server has quit!");
			} catch (InterruptedException e) { e.printStackTrace(); }
		}
	}
    
    // This registers objects that are going to be sent over the network.
    static public void register (EndPoint endPoint) {
            Kryo kryo = endPoint.getKryo();
            kryo.register(ArrayList.class);
            kryo.register(RegisterName.class);
            kryo.register(SimpleUnit.class);
            kryo.register(UnitType.class);
    }

    static public class RegisterName {
            public String name;
    }
    
    //Allows for naming of connections by player name or by playerNumber
    static public class WarTugConnection extends Connection {
    	public String name;
    	public int playerNum;
    }

}

